﻿using Newtonsoft.Json;
using SynologyDotNet;
using System;
using ExcelConfig.Config;

namespace SynologyLIB
{
    using synoexec.synoexec.synologylib.Helpers;
    using synoexec.synoexec.synologylib.Model;
    using synoexec.synoexec.synologylib.Responses;
    using synoexec.synologylib.DataType;
    public class MySyno
    {
        /// <summary>
        /// 验证账户密码有效性
        /// </summary>
        public static async Task<bool> VertiyAccount(string uri, string account, string password, bool bypassSslCertificateValidation = true)
        {
            var client = new SynoClient(new Uri(uri), bypassSslCertificateValidation);
            return await client.VerityAccountAsync(account, password);
        }
        /// <summary>
        /// 修改密码
        /// </summary>
        public async Task<bool> ChangePassword(string password, string oldpassword)
        {
            var api = _synology_config.Text("修改密码");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("password", password),
                ("old_password", oldpassword));

            var res = await Client.QueryObjectAsync<ApiResponse>(api, method, _pm.ToArray());
            return res.Success;
        }

        public async Task ReadACL(string path)
        {
            var api = _synology_config.Text("查看权限");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("file_path", path));

            var res = await Client.QueryObjectAsync<ApiResponse>(api, method, _pm.ToArray());
        }
        protected SynoClient Client { get; set; }
        internal AppConfigFile _synology_config { get; set; }
        public MySyno(SynoClient client)
        {
            this.Client = client;
            this._synology_config = new AppConfigFile("./config", "synology");
            this._synology_config.GotoSheet("接口");
        }
        /// <summary>
        /// 登录，同时获取接口列表
        /// </summary>
        public async Task LoginAsync(string user, string password)
        {
            await Client.LoginAsync(user, password);
            await Client.QueryApiInfos(); //初始化接口列表
        }
        /// <summary>
        /// 默认值生成
        /// </summary>
        internal (string, object)[] GetDefaultValue(string source, params (string, object)[] values)
        {
            var _pm = new List<(string, object)>();
            var _vn = values.Select(t => t.Item1);
            foreach (var param in source.Split(";"))
            {
                var _1 = param.Split(":");
                if (_1.Length != 2) continue;
                var _name = _1[0].Trim();
                var _value = _1[1].Trim();

                if (_vn.Contains(_name)) continue;
                _pm.Add((_1[0].Trim(), _1[1].Trim()));
            }
            foreach (var v in values)
            {
                if (v.Item2.GetType().IsArray)
                {
                    _pm.Add((v.Item1, JsonConvert.SerializeObject(v.Item2)));
                    continue;
                }
                _pm.Add(v);
            }
            return _pm.ToArray();
        }
        internal string o(params (string, object)[] values)
        {
            var dict = new Dictionary<string, object>();
            foreach(var v in values) dict[v.Item1] = v.Item2;
            return JsonConvert.SerializeObject(dict);
        }
        /// <summary>
        /// 读取日志
        /// </summary>
        public async Task<ApiDataResponse<LogCenterLog>> ReadLogs(string target, int current_page, int page_size, string search_text = "")
        {
            var api = _synology_config.Text("日志查阅");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("target", target),
                ("limit", page_size),
                ("offset", ((current_page - 1) * page_size)),
                ("keyword", search_text));

            var res = await Client.QueryObjectAsync<ApiDataResponse<LogCenterLog>>(api, method, _pm.ToArray());

            return res;
        }
        /// <summary>
        ///检查文件权限
        /// </summary>
        public async Task<ApiDataResponse<CheckPermissionOutput>> CheckFilePermission(string path, string filename, long size, bool overwrite)
        {
            var api = _synology_config.Text("检查文件权限");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("path", path),
                ("filename", filename),
                ("size", size),
                ("overwrite", overwrite));

            var res = await Client.QueryObjectAsync<ApiDataResponse<CheckPermissionOutput>>(api, method, _pm.ToArray());
            
            return res;
        }
        /// <summary>
        /// 删除文件
        /// </summary>
        public async Task<ApiDataResponse<TaskInfo>> DeleteFile(params string[] path)
        {
            var api = _synology_config.Text("删除文件");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("path", path));

            var res = await Client.QueryObjectAsync<ApiDataResponse<TaskInfo>>(api, method, _pm.ToArray());

            return res;
        }
        /// <summary>
        /// 删除状态
        /// </summary>
        public async Task<ApiDataResponse<DeleteStatus>> DeleteFileStatus(string taskid)
        {
            var api = _synology_config.Text("查询删除进度");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("taskid", taskid));

            var res = await Client.QueryObjectAsync<ApiDataResponse<DeleteStatus>>(api, method, _pm.ToArray());
            return res;
        }
        /// <summary>
        /// 列出目录
        /// </summary>
        public async Task<ApiDataResponse<FileListItem>> ListFolder(string path)
        {
            var api = _synology_config.Text("读取文件列表");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("folder_path", path));

            var res = await Client.QueryObjectAsync<ApiDataResponse<FileListItem>>(api, method, _pm.ToArray());
            if (!res.Success) throw new Exception(res.ErrorDescription);
            var filters_path = _synology_config.ExcelConfig.ReadGlobal<string>("过滤文件夹").Split(";");
            //过滤一些缩略图文件
            var filters_file = _synology_config.ExcelConfig.ReadGlobal<string>("过滤文件").Split(";");
            var oldlen = res.Data.Files.Length;
            var filters = filters_path.Concat(filters_file);

            res.Data.Files = res.Data.Files.Where(t => !filters.Contains(t.Name)).ToArray();
            res.Data.Total -= oldlen - res.Data.Files.Length;
            return res;
        }
        /// <summary>
        /// 上传文件
        /// </summary>
        public async Task<ApiDataResponse<UploadInfo>> UploadFile(string path, string filename, Stream stream, bool overwrite)
        {
            var api = _synology_config.Text("文件上传");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("overwrite", overwrite),
                ("path", path),
                ("mtime", TimeHelper.GetJsTime(DateTime.UtcNow)),
                ("size", stream.Length));

            var res = await Client.QueryObjectAsync<ApiDataResponse<UploadInfo>>(api, method, stream, filename, _pm.ToArray());
            return res;
        }
        /// <summary>
        /// 读取共享列表
        /// </summary>
        public async Task<ApiDataResponse<ShareItems>> ListShareFolder()
        {
            var api = _synology_config.Text("读取共享列表");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params);

            var res = await Client.QueryObjectAsync<ApiDataResponse<ShareItems>>(api, method, _pm.ToArray());
            return res;
        }
        /// <summary>
        /// 读取系统存储信息
        /// </summary>
        public async Task<ApiDataResponse<StorageInfo>> ReadStorageInfo()
        {
            var api = _synology_config.Text("读取存储信息");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params);

            var res = await Client.QueryObjectAsync<ApiDataResponse<StorageInfo>>(api, method, _pm.ToArray());
            return res;
        }
        /// <summary>
        /// 重命名文件
        /// </summary>
        public async Task<ApiDataResponse<FileListItem>> RenameFile(string path, string newName)
        {
            var api = _synology_config.Text("重命名文件");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("path", new string[] { path }),
                ("name", new string[] { newName }));

            var res = await Client.QueryObjectAsync<ApiDataResponse<FileListItem>>(api, method, _pm.ToArray());
            return res;
        }
        /// <summary>
        /// 新建文件夹
        /// </summary>
        public async Task<ApiDataResponse<FileListItem>> NewFolder(string path, string name)
        {
            var api = _synology_config.Text("新建文件夹");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("folder_path", path),
                ("name", name));

            var res = await Client.QueryObjectAsync<ApiDataResponse<FileListItem>>(api, method, _pm.ToArray());
            return res;
        }
        /// <summary>
        /// 移动文件
        /// </summary>
        public async Task<ApiDataResponse<TaskInfo>> MoveFile(string dest_path, params string[] paths)
        {
            var api = _synology_config.Text("移动文件");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("path", paths),
                ("dest_folder_path", dest_path));

            var res = await Client.QueryObjectAsync<ApiDataResponse<TaskInfo>>(api, method, _pm.ToArray());
            return res;
        }
        /// <summary>
        /// 查询移动进度
        /// </summary>
        public async Task<ApiDataResponse<MoveStatus>> MoveFileStatus(string taskid)
        {
            var api = _synology_config.Text("查询移动进度");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("taskid", taskid));

            var res = await Client.QueryObjectAsync<ApiDataResponse<MoveStatus>>(api, method, _pm.ToArray());
            return res;
        }
        /// <summary>
        /// 读取备份任务
        /// </summary>
        public async Task<ApiDataResponse<BackupTaskList>> ReadActiveBackupTasks()
        {
            var api = _synology_config.Text("读取备份任务");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params);

            var res = await Client.QueryObjectAsync<ApiDataResponse<BackupTaskList>>(api, method, _pm.ToArray());
            return res;
        }
        /// <summary>
        /// 读取备份版本列表
        /// </summary>
        public async Task<ApiDataResponse<BackupTaskList>> ReadActiveBackupVersions(int taskid, int current_page, int page_size)
        {
            var api = _synology_config.Text("读取备份版本列表");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("limit", page_size),
                ("offset", ((current_page - 1) * page_size)),
                ("filter", o(("limit", page_size), ("offset", ((current_page - 1) * page_size)), ("task_id", taskid),("data_formats", new int[] { 1, 4 }))));

            var res = await Client.QueryObjectAsync<ApiDataResponse<BackupTaskList>>(api, method, _pm.ToArray());
            return res;
        }
        /// <summary>
        /// 开始备份任务
        /// </summary>
        public async Task<ApiResponse> StartActiveBackup(params int[] taskid)
        {
            var api = _synology_config.Text("开始备份任务");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("task_ids", taskid));

            var res = await Client.QueryObjectAsync<ApiResponse>(api, method, _pm.ToArray());
            return res;
        }
        
        /// <summary>
        /// 下载文件
        /// </summary>
        public async Task DownloadFile(string path, Action<StreamResult> readStreamAction)
        {
            var filename = Path.GetFileName(path);
            var hexpath = TextHelper.ToHex(path);

            //filename 需要url 编码
            await Client.ReadStreamAsync($"fbdownload/{System.Web.HttpUtility.UrlEncode(filename)}", readStreamAction, 
                ("dlink", hexpath),
                ("noCache", TimeHelper.GetJsTime(DateTime.UtcNow).ToString()),
                ("mode", "download"),
                ("stdhtml", "false"));
        }

        /// <summary>
        /// 打开文件
        /// </summary>
        public async Task OpenFile(string path, Action<StreamResult> readStreamAction)
        {
            var filename = Path.GetFileName(path);
            var hexpath = TextHelper.ToHex(path);

            //filename 需要url 编码
            await Client.ReadStreamAsync($"fbdownload/{System.Web.HttpUtility.UrlEncode(filename)}", readStreamAction,
                ("dlink", hexpath),
                ("noCache", TimeHelper.GetJsTime(DateTime.UtcNow).ToString()),
                ("mode", "open"),
                ("stdhtml", "true"));
        }
        /// <summary>
        /// 开始计算文件md5
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public async Task<ApiDataResponse<TaskInfo>> StartCalcMD5(string path)
        {
            var api = _synology_config.Text("开始计算md5");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("file_path", path));

            var res = await Client.QueryObjectAsync<ApiDataResponse<TaskInfo>>(api, method, _pm.ToArray());
            return res;
        }
        /// <summary>
        /// 读取正在计算的md5信息
        /// </summary>
        /// <param name="taskid"></param>
        /// <returns></returns>
        public async Task<ApiDataResponse<MD5Info>> ReadMD5(string taskid)
        {
            var api = _synology_config.Text("读取md5");
            var method = _synology_config.ExcelConfig.ReadOther<string>("动作");
            var default_params = _synology_config.ExcelConfig.ReadOther<string>("默认值");
            var _pm = GetDefaultValue(default_params,
                ("taskid", taskid));

            var res = await Client.QueryObjectAsync<ApiDataResponse<MD5Info>>(api, method, _pm.ToArray());
            return res;
        }
    }
}
